package main

import (
	"fmt"
	"io/ioutil"
	"james.org/sister/core"
	"log"
	"net/http"
	"path/filepath"
	"time"
)

type SingleTasks struct {
	Tasks []SingleTask
}

type SingleTask struct {
	Log            bool
	Save           bool
	SetHeader      bool
	RequestTimeout int
	Dir            string
	Sources        []string
	Prey           core.Prey
	Pagination     core.Pagination
}

func RunSingleTask(jsonPath string) {
	// 读取JSON文件任务
	var singleTasks SingleTasks
	err := core.DecodeJsonFile(jsonPath, &singleTasks)
	if err != nil {
		fmt.Println(err)
	}
	for _, singleTask := range singleTasks.Tasks {
		// 创建目录
		err = core.MkDirAll("./save/" + singleTask.Dir)
		if err != nil {
			fmt.Println(err)
		}
		// 分页分析
		var pages []string
		for _, source := range singleTask.Sources {
			pagesTemp, err := core.PaginationUrlAnalysis(source, singleTask.Pagination)
			if err != nil {
				fmt.Println(err)
			}
			pages = append(pages, pagesTemp...)
		}
		log.Println("页面分析完毕")
		// 分页结果日志记录
		logPath := "./logs/" + singleTask.Dir + ".log"
		if singleTask.Log {
			err := core.WriteLogs(logPath, pages, true)
			if err != nil {
				log.Println(err)
			}
		}
		// 猎物分析
		var preys []string
		chs := make([]chan []string, len(pages))
		runPage := func(task_id int, page string, ch chan []string) {
			log.Printf("%v--%v--%v\n", task_id, page, len(ch))
			results, err := core.UrlAnalysis(page, singleTask.Prey)
			if err != nil {
				log.Println(err)
			}
			log.Println("result lenth:" + string(len(results)))

			if singleTask.Log {
				core.WriteLogs(logPath, results, true)
			}
			preys = append(preys, results...)
			chs[task_id] <- results
		}
		for task_id, page := range pages {
			chs[task_id] = make(chan []string, 1)
			go runPage(task_id, page, chs[task_id])
		}
		// 等待分析
		for _, ch := range chs {
			<-ch
		}
		fmt.Println("猎物分析完毕")
		// 猎物捕捉
		if singleTask.Save {
			client := http.Client{
				Timeout: time.Second * time.Duration(singleTask.RequestTimeout),
			}
			filePath := "./save/" + singleTask.Dir
			phs := make([]chan int, len(preys))
			savePrey := func(pid int, prey string, ph chan int) {
				var resp *http.Response
				if singleTask.SetHeader {
					req, err := http.NewRequest("GET", prey, nil)
					if err != nil {
						fmt.Println(err)
					}
					req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36")
					req.Header.Set("Referer", prey)
					resp, err = client.Do(req)
				} else {
					resp, err = client.Get(prey)
				}
				if err != nil {
					fmt.Println(err)
				} else {
					data, _ := ioutil.ReadAll(resp.Body)
					resp.Body.Close()
					path := fmt.Sprintf("%s/pid_%d_%s", filePath, pid, filepath.Base(prey))
					err = core.SaveFile(path, data)
					if err != nil {
						fmt.Println(err)
					} else {
						fmt.Println("已捕捉: " + prey)
					}
				}
				phs[pid] <- pid
			}
			for pid, prey := range preys {
				phs[pid] = make(chan int, 1)
				go savePrey(pid, prey, phs[pid])
			}
			// 等待捕捉
			for _, ph := range phs {
				<-ph
			}
		}
		// 结束
		fmt.Println("任务已处理完毕")
	}
}
